D3 single axis jitterplot pan and zoom
transitionを消した
preactで書き換えた
こんなことやっている暇あるのか……?takker.icon
code:app.js
const { randomNormal, randomUniform, scaleLinear, select, zoom, interpolateInferno, axisLeft } = d3;
// data
// y成分は正規分布、x成分は一様分布で作る
const y = randomNormal(400, 100);
const x_jitter = randomUniform(-100, 100);
const ys = points.map((y) => y);
const extent = [
Math.min(...ys),
Math.max(...ys),
];
// fill
*
* 0, 1に変換した値を、色を決定する関数に渡して色を得る */
const colorScale = scaleLinear()
.domain(extent)
// dimensions
const margin = { top: 20, right: 20, bottom: 30, left: 40 },
svg_dx = 330,
svg_dy = 500;
const chart_dx = svg_dx - margin.right - margin.left;
const chart_dy = svg_dy - margin.top - margin.bottom;
/** y成分をグラフ上の座標に変換する */
const yScale = scaleLinear()
.domain(extent)
// y-axis
const yAxis = axisLeft(yScale);
const { html, render, useState, useCallback, useEffect } = htmPreact;
const App = () => {
code:app.js
const handleMount = useCallback((svg) => {
if (!svg) return;
select(svg).call(
zoom().on("zoom", (e) => {
setYScale(() => e.transform.rescaleY(yScale));
}),
}, []);
code:app.js
useEffect(() => {
// re-scale y axis during zoom; ref 2 select(g).call(yAxis.scale(new_yScale));
code:app.js
return html`
<svg width=${svg_dx} height=${svg_dy} ref=${handleMount}>
<g transform="translate(200, 0)">
${points.map((x, y) => html` re-draw circles using new y-axis scale
code:app.js
<circle cx=${x} cy=${new_yScale(y)} r="4" fill=${interpolateInferno(colorScale(y))} />
`)}
</g>
<g transform="translate(75,0)" ref=${setG} />
</svg>
`;
}
render(html<${App} />, document.body);